package linz

/**
 * Created by prefert on 2019/5/13.
 */
open class Base

class Extended : Base()

fun Base.foo() = "I'm Base.foo!"
fun Extended.foo() = "I'm Extended.foo!"

open class X {
    open fun Base.foo() {
        println("I’m Base.foo in X")
    }

    open fun Extended.foo() {
        println("I’m Extended.foo in X")
    }

    fun deal(base: Base) {
        base.foo()
    }
}

class Y : X() {
    override fun Base.foo() {
        println("I’m Base.foo in Y")
    }

    override fun Extended.foo() {
        println("I’m Extended.foo in Y")
    }

}

fun main(args: Array<String>) {
    val instance: Base = Extended()
    val instance2 = Extended()
    println(instance.foo()) // I'm Base.foo!
    println(instance2.foo()) // I'm Extended.foo!

    /**
     * https://stackoverflow.com/questions/60473476/extension-function-is-virtual-to-dispatch-reciever
     * With the Extensions are resolved statically point we have established that no matter which object you pass (Base or Derived) the call function will always invoke an extension function defined on the Base type.

    But which extension function will be invoked? one in the Base class or the one in Derived class ?

    This depends on the type of object which invokes the call function, if you invoke the call with an Object of Base then the extension in the base class will be invoked and if you use the Derived object then the extension in Derived class will be invoked.
     */
    X().deal(instance) // 输出 I’m Base.foo in X
    Y().deal(instance) // 输出I’m Base.foo in Y — 即 dispatch receiver 被动态处理
    X().deal(instance2) // 输出I’m Base.foo in X — 即 extension receiver 被静态处理
    Y().deal(instance2) // 输出I’m Base.foo in Y
}
